//Pseudo Dual port Multibank SPSRAM specially for ysyx project
//Write First arbite configuration

// pDPRAM non-blocked operation Timing:
//  CLK   :____/----\____/----\____/----\____/----\____/----\____/----\
//  raddr :----< ADDR0 > < ADDR1 > < ADDR2 > < ADDR3 > ----------------
//  rbank :----< BANKx > <           BANKy           > ----------------
//  dato  :--------------< DATA0 > < DATA1 > < DATA2 > < DATA3 > ------
//  rvalid:______________/---------------------------------------\_____
//  waddr :----< ADDR0 > < ADDR1 > < ADDR2 > < ADDR3 > < ADDR4 > ------
//  wbank :----< BANKa > <      BANKb      > <      BANKc      > ------
//  wbsel :----< BSELf > < BSEL4 > < BSEL7 > < BSEL1 > < BSEL4 > ------
//  dati  :----< DATA0 > < DATA1 > < DATA2 > < DATA3 > < DATA4 > ------
//  wcfrm :______________/---------------------------------------------

// pDPRAM blocked aligned write operation Timing: (USING BYTE ENABLE ALWAYS USE THIS)
//  Read       |<-Addr1->|<-Block->|<-Addr2->|
//                       |<-Data1->|<-Block->|<-Data2->|
//  Write                |<-Addr1->|
//                       |<-Write->|<-OKAY ->|
//  CLK   :____/----\____/----\____/----\____/----\____/----\____/----\
//  raddr :----< ADDR0 > < ADDR1      HOLD > < ADDR2 > ----------------
//  rbank :----< BANKx                     > --------------------------
//  dato  :--------------< DATA0 > < XXXXX > < DATA1 > < DATA2 > ------
//  rvalid:______________/---------\_________/-------------------------
//  waddr :------------- < ADDR0 > ------------------------------------
//  wbank :------------- < BANKx > ------------------------------------
//  wbsel :------------- < BSELf > ------------------------------------
//  dati  :------------- < DATA1 > ------------------------------------
//  wcfrm :________________________/---------\_________________________
`include "PRV564Config.v"
`include "PRV564Define.v"
module pDPRAM_ysyx
#
(
    parameter BANK_COEFF=3
)
(
    input [5:0]raddr,
    input [BANK_COEFF-1:0]rbank,
    input rdce,
    output [127:0]dato,
    output rvalid,
    input [5:0]waddr,
    input [BANK_COEFF-1:0]wbank,
    input [15:0]wbsel,
    input [127:0]dati,
    input clk,rst
);
    localparam BANK_NUM=(2**BANK_COEFF);
    wire [127:0]RdPortBankDat[BANK_NUM-1:0];
    wire [127:0]wmask;
    wire [BANK_NUM-1:0]RdBankSel,WrBankSel;
    wire rw_block;
    wire write;
    assign write=(wbsel!=0);
    reg rvalid_reg;
    reg [BANK_COEFF-1:0]rbank_sel;
    assign rvalid = rvalid_reg;
    assign wmask= ~{
                    {8{wbsel[15]}},
                    {8{wbsel[14]}},
                    {8{wbsel[13]}},
                    {8{wbsel[12]}},
                    {8{wbsel[11]}},
                    {8{wbsel[10]}},
                    {8{wbsel[9]}},
                    {8{wbsel[8]}},
                    {8{wbsel[7]}},
                    {8{wbsel[6]}},
                    {8{wbsel[5]}},
                    {8{wbsel[4]}},
                    {8{wbsel[3]}},
                    {8{wbsel[2]}},
                    {8{wbsel[1]}},
                    {8{wbsel[0]}}
                };
    assign rw_block=(rbank == wbank);
    assign dato=RdPortBankDat[rbank_sel];
    
    genvar i;
    generate
    for(i=0;i<BANK_NUM;i=i+1)//Bank Select Signal Generation
    begin : BANKSEL_GEN
        assign RdBankSel[i]=~((rbank == i) & rdce);
        assign WrBankSel[i]=~((wbank == i) & (wbsel != 0));
    end

    for(i=0;i<BANK_NUM;i=i+1)//Cache Ram Generation
    begin:CACHE_RAM_GEN
        S011HD1P_X32Y2D128_BW CACHEMEM
        (
            .Q(RdPortBankDat[i]), 
            .CLK(clk), 
            .CEN(1'b0), //RdBankSel[i]&WrBankSel[i]
            .WEN(WrBankSel[i]), 
            .BWEN(wmask),
            .A((!WrBankSel[i])?waddr:raddr), 
            .D(dati)
        );    
    end
    endgenerate

    always@(posedge clk or posedge rst)//read arbiter
    if(rst)
        rvalid_reg<=0;
    else
        rvalid_reg<=rdce & (!(rw_block & write));
    always@(posedge clk)
        rbank_sel<=rbank;
endmodule
